package com.PlantVsZombies.ui;

import java.awt.Graphics;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;

import com.PlantVsZombies.Bullet.Bomb;
import com.PlantVsZombies.Bullet.Bullet;
import com.PlantVsZombies.Bullet.SunCollection;
import com.PlantVsZombies.Plants.CherryPlant;
import com.PlantVsZombies.Plants.PeaPlant;
import com.PlantVsZombies.Plants.QhPlant;
import com.PlantVsZombies.Plants.SmallStonePlant;
import com.PlantVsZombies.Plants.Sun;
import com.PlantVsZombies.Plants.SunFlower;
import com.PlantVsZombies.Zombies.LostHead;
import com.PlantVsZombies.Zombies.Pass;
import com.PlantVsZombies.common.Life;
import com.PlantVsZombies.common.Plant;
import com.PlantVsZombies.common.Zombie;
import com.PlantVsZombies.constant.Constant;
import com.PlantVsZombies.constant.PlantType;
import com.PlantVsZombies.online.DataTransfer;
import com.PlantVsZombies.util.ImageUtil;
import com.PlantVsZombies.util.MusicPlay;
import com.PlantVsZombies.util.MusicUtil;

public class PlantsMap extends Life implements Constant, Serializable{

	// 每个地图的格子
	private Plant[][] plantsMap;
	// 格子上是否是僵尸
	boolean[][] isZombie;
	// 格子是否是植物
	boolean[][] isPlant;
	private int sunIndex = 0;
	private int produceZombieSpeed = 0;
	MusicPlay mp = new MusicPlay("music/plant.wav");
	MusicPlay plantSun = new MusicPlay("music/loadingbar_flower.wav");
	MusicPlay shoot = new MusicPlay(MusicUtil.KERN);
	// 僵尸
	public static ArrayList<Zombie> zombies = new ArrayList<Zombie>();
	// 植物
	public static ArrayList<Plant> plants = new ArrayList<Plant>();
	// 阳光
	private static ArrayList<Sun> sun = new ArrayList<Sun>();
	// 爆炸
	public static ArrayList<Bomb> bomb = new ArrayList<Bomb>();
	public static ArrayList<SunCollection> sunCollections = new ArrayList<SunCollection>();
	public static ArrayList<LostHead> LostHead = new ArrayList<LostHead>();
	public static boolean isLive = true;
	DataTransfer transfer = null;
	
	// 收集阳光音效

	public DataTransfer getTransfer() {
		return transfer;
	}

	public void setTransfer(DataTransfer transfer) {
		this.transfer = transfer;
	}

	public PlantsMap() {
		plantsMap = new Plant[MAP_ROW][MAP_COL];
		isZombie = new boolean[MAP_ROW][MAP_COL + 5];
		isPlant = new boolean[MAP_ROW][MAP_COL];

		for (int i = 0; i < MAP_ROW; i++) {
			for (int j = 0; j < MAP_COL; j++) {
				isZombie[i][j] = false;
				isPlant[i][j] = false;
			}
		}
	}

	public ArrayList<Zombie> getZombies() {
		return zombies;
	}

	public void setZombies(ArrayList<Zombie> zombies) {
		this.zombies = zombies;
	}

	public ArrayList<Plant> getPlants() {
		return plants;
	}
	public static ArrayList<Sun> getSun() {
		return sun;
	}

	public static void setSun(ArrayList<Sun> sun) {
		PlantsMap.sun = sun;
	}

	public void setPlants(ArrayList<Plant> plants) {
		this.plants = plants;
	}

	public static ArrayList<Bomb> getBomb() {
		return bomb;
	}

	public static void setBomb(ArrayList<Bomb> bomb) {
		PlantsMap.bomb = bomb;
	}

	public static ArrayList<LostHead> getLostHead() {
		return LostHead;
	}

	public static void setLostHead(ArrayList<LostHead> lostHead) {
		LostHead = lostHead;
	}

	// 绘制所种植物
	public void drawPlant(Graphics g) {
		for (int i = 0; i < MAP_COL; ++i) {
			for (int j = 0; j < MAP_ROW; ++j) {
				int x = MAP_WEST_OFFSET + i * MAP_RECT_WIDTH;
				int y = MAP_TOP_OFFSET + j * MAP_RECT_HEIGHT;

				Plant p = plantsMap[j][i];
				if (p != null) {
					if (p.isLive())
						p.drawMe(g, x, y);
					else {
						// 设置格子上没植物
						isPlant[j][i] = false;
						// 集合移除植物
						//plants.remove(p);
					}
				}
			}
		}
	}

	// 画僵尸
	public void drawZombie(Graphics g) {
		Collections.sort(zombies);
		for (int i = 0; i < zombies.size(); i++) {
			if (zombies.get(i).getLive()) {
				zombies.get(i).drawImage(g);
			} else {
				zombies.remove(i);
			}
		}
	}

	// 画阳光
	public void drawSun(Graphics g) {
		for (int i = 0; i < sun.size(); i++) {
			if (sun.get(i).isLive()) {
				sun.get(i).drawMe(g);
			} else {
				sun.remove(i);
			}
		}
	}

	// 画爆炸
	public void drawBomb(Graphics g) {
		for (int i = 0; i < bomb.size(); i++) {
			if (bomb.get(i).getLive()) {
				bomb.get(i).drawMe(g);
			} else {
				bomb.remove(i);
			}
		}
	}
	// 画爆炸
	public void drawHead(Graphics g) {
		for (int i = 0; i < LostHead.size(); i++) {
			LostHead.get(i).paintHead(g);
		}
	}
	// 画爆炸
	public void drawSunCollection (Graphics g) {
		for (int i = 0; i < sunCollections.size(); i++) {
			sunCollections.get(i).drawMe(g);
		}
	}

	// 坐标是否在当前草坪范围内
	public boolean inTheMap(int posX, int posY) {
		if ((posX > MAP_WEST_OFFSET)
				&& (posX < MAP_WEST_OFFSET + MAP_COL * MAP_RECT_WIDTH)
				&& (posY > MAP_TOP_OFFSET)
				&& (posY < MAP_TOP_OFFSET + MAP_ROW * MAP_RECT_HEIGHT)) {
			return true;
		}
		return false;
	}

	// 将所选植物种入相应的草坪块中
	public boolean putPlantInMap(PlantType pt, int posX, int posY) {
		Plant p = null;
		switch (pt) {
			case SunFlower:
				p = new SunFlower(posX, posY);
				plantSun.replay();
				break;
			case SingleBullet:
				p = new PeaPlant(posX, posY);
				mp.replay();
				break;
			case Cherry:
				p = new CherryPlant(posX, posY);
				mp.replay();
				break;
			case SmallStone:
				p = new SmallStonePlant(posX, posY);
				mp.replay();
				break;
			case QH1:
				p = new QhPlant(posX, posY, PlantType.QH1);
				mp.replay();
				break;
			case QH2:
				p = new QhPlant(posX, posY, PlantType.QH2);
				mp.replay();
				break;
			case QH3:
				p = new QhPlant(posX, posY, PlantType.QH3);
				mp.replay();
				break;
		}
		new Thread(p).start();
		plants.add(p);
		if (p != null) {
			int col = (posX - MAP_WEST_OFFSET) / MAP_RECT_WIDTH; // 得到列
			int row = (posY - MAP_TOP_OFFSET) / MAP_RECT_HEIGHT; // 得到行
			if (!isPlant[row][col]) {
				plantsMap[row][col] = p;
				isPlant[row][col] = true;
				if (transfer != null) {
					transfer.sendObjData(p);
				}
				return true;
			} else
				return false;
		}
		return false;
	}

	/**
	 * 
	 * 方法，设置每个植物是否可以发射子弹 获取植物坐标 判断坐标位置，在哪块土地 土地那行是否有僵尸
	 */
	public void setShoot() {

		for (int i = 0; i< plants.size(); i++) {
			Plant pl = plants.get(i);
			if (pl != null && pl.getType() == PlantType.SingleBullet) {
				int col = (pl.x - MAP_WEST_OFFSET) / MAP_RECT_WIDTH; // 得到列
				int row = (pl.y - MAP_TOP_OFFSET) / MAP_RECT_HEIGHT; // 得到行
				if (checkHasZombie(row, col)) {
					pl.canShoot = true;
				} else {
					pl.canShoot = false;
				}
			}
		}
	}

	/**
	 *  检测植物右侧是否有僵尸
	 * @param x
	 * @param y
	 * @return
	 */
	public boolean checkHasZombie(int x, int y) {
		for (int i = 0; i < zombies.size(); i++) {
			Zombie zb = zombies.get(i);
			int col = (zb.getRow() - MAP_WEST_OFFSET) / MAP_RECT_WIDTH; // 得到列
			int row = (zb.getCol() + 98 - MAP_TOP_OFFSET) / MAP_RECT_HEIGHT; // 得到行
			if (x == row && col < 8 && zb.getLife() > 0) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 判断是否点击了阳光
	 * @param x
	 * @param y
	 * @return
	 */
	public int collectSun(int x, int y) {

		int sum = 0;

		Iterator<Sun> it = sun.iterator();
		while (it.hasNext()) {
			Sun s = it.next();
			int num = s.isClicked(x, y);
			if (num > 0) {
				sum += num;
				SunCollection sc = new SunCollection(s.x, s.y, null);
				sc.start();
				sunCollections.add(sc);
				it.remove();
			}
		}
		return sum;

	}

	/**
	 * 生产阳光
	 */
	public void produceSun() {
		for (Plant pl : plants) {
			if (pl.getType() == PlantType.SunFlower) {

				SunFlower sunflower = (SunFlower) pl;

				Sun s = sunflower.producelight();
				s.start();
				sun.add(s);
			}
		}

	}

	/**
	 * 攻击僵尸
	 */
	public void attackZombie() {
		/*
		 * 
		 * 遍历所有植物 判断植物类型 获取不同植物类型发射的子弹
		 */
		for (int i = 0; i < plants.size(); i++) {
			Plant plant = plants.get(i);
			switch (plant.getType()) {
			case SingleBullet:
				PeaPlant pp = (PeaPlant) plant;
				// 获取子弹集合
				ArrayList<Bullet> bullet = pp.getBullet();
				// 攻击僵尸
				isAttacked(bullet, zombies);
				// 被僵尸攻击
				zombieAttack(pp);
				break;
			case Cherry:
				CherryPlant cp = (CherryPlant) plant;
				int Ccol = (cp.x - MAP_WEST_OFFSET) / MAP_RECT_WIDTH; // 得到列
				int Crow = (cp.y + 98 - MAP_TOP_OFFSET) / MAP_RECT_HEIGHT - 1; // 得到行

				for (Zombie zb : zombies) {
					int Zcol = (zb.getRow() - MAP_WEST_OFFSET) / MAP_RECT_WIDTH; // 得到列
					int Zrow = (zb.getCol() + 98 - MAP_TOP_OFFSET)
							/ MAP_RECT_HEIGHT; // 得到行

					if (cp.life == 1) {
						if (Zcol >= Ccol - 2 && Zcol <= Ccol
								&& Zrow >= Crow - 1 && Zrow <= Crow + 1) {
							zb.setLife(-10);
						}
					}
				}

				break;
			case SmallStone:
				SmallStonePlant sp = (SmallStonePlant) plant;
				zombieAttack(sp); // 僵尸攻击土豆
				break;
			case SunFlower:
				SunFlower sf = (SunFlower) plant;
				zombieAttack(sf);
				break;
			case QH2:
			case QH3:
			case QH1:
				int Qcol = (plant.x - MAP_WEST_OFFSET) / MAP_RECT_WIDTH; // 得到列
				int Qrow = (plant.y + 98 - MAP_TOP_OFFSET) / MAP_RECT_HEIGHT
						- 1; // 得到行

				for (Zombie zb : zombies) {
					int Zcol = (zb.getRow() - MAP_WEST_OFFSET) / MAP_RECT_WIDTH; // 得到列
					int Zrow = (zb.getCol() + 98 - MAP_TOP_OFFSET)
							/ MAP_RECT_HEIGHT; // 得到行

					if (Zcol >= Qcol && Zcol <= Qcol + 3 && Zrow >= Qrow - 1
							&& Zrow <= Qrow) {
						zb.setLife(zb.getLife()-1);
					}
				}
				if(!plant.isLive()){
					plants.remove(plant);
				}

				break;
			default:
				break;
			}

		}
	}

	public void zombieAttack(Plant plant) {

		
		int Scol = (plant.x - MAP_WEST_OFFSET) / MAP_RECT_WIDTH; // 得到列
		int Srow = (plant.y + 98 - MAP_TOP_OFFSET) / MAP_RECT_HEIGHT - 1; // 得到行
		for (int i = 0; i < zombies.size(); i++) {
			Zombie zb = zombies.get(i);
			int Zcol = (zb.getRow() - MAP_WEST_OFFSET + 80) / 80; // 得到列
			int Zrow = (zb.getCol() + 98 - MAP_TOP_OFFSET) / MAP_RECT_HEIGHT; // 得到行
			if (Srow == Zrow) {
				if (Scol == Zcol) {
					if (plant.life > 0) {
						zb.setAttack(true);
						zb.setCanRun(false);
						plant.setAttacked(true);
					} else {
						zb.setAttack(false);
						zb.setCanRun(true);
						plant.setAttacked(false);
						plants.remove(plant);
					}
				}
			}
		}
	}

	/**
	 * 
	 * 击中僵尸
	 * 
	 * @param bullet
	 * 
	 * @param zombie
	 */
	public void isAttacked(ArrayList<Bullet> bullet, ArrayList<Zombie> zombie) {
		for (int i = 0; i < bullet.size(); i++) {
			Bullet bt = bullet.get(i);
			for (Zombie zb : zombie) {
				if (bt.getX() > zb.getRow()
						&& bt.getX() < zb.getRow() + Normal_Zombie_WIDTH
						&& bt.getY() > zb.getCol()
						&& bt.getY() < zb.getCol() + Normal_Zombie_HEIGHT
						&& zb.getLife()>0) {

					/*
					 * 若击中 子弹死亡 僵尸生命减少 添加爆炸
					 */

					bt.setLive(false);// 子弹死亡
					zb.setLife(zb.getLife() - 1); // 僵尸生命减一

					shoot.replay();
					Bomb bm = new Bomb(bt.getX(), bt.getY(), ImageUtil.bomb1);// 添加爆炸
					bm.start();
					bomb.add(bm);
					return;
				}
			}
		}
	}

	public void isGameOver() {
		
		for (int i = 0; i < zombies.size(); i++) {
			if (zombies.get(i).getRow() < -10) {
				GamePanel.gamestate = "gameover";
				plants.removeAll(plants);
				zombies.removeAll(zombies);
			}
		}
		if(Pass.zombieNum <= 0 && zombies.size() == 0){
			GamePanel.isPass = true;
		}
	}
	public static boolean hasPlant(int row, int col){
		for(int i = 0 ; i < plants.size(); i++){
			Plant plant = plants.get(i);
		int Scol = plant.x; // 得到列
		int Srow = (plant.y + 98 - MAP_TOP_OFFSET) / MAP_RECT_HEIGHT - 1; // 得到行	
		int Zcol = row; // 得到列
		int Zrow = (col + 98 - MAP_TOP_OFFSET)/ MAP_RECT_HEIGHT; // 得到行
		if(Scol/3 == Zcol/3 && Srow == Zrow)
			return true;
		}		
		return false;
	}
	
	public boolean isPlant(int row, int col) {
		return isPlant[row][col];
	}
	
	public void removePlant(int row, int col) {
		plantsMap[row][col].life = 0;
	}


	@Override
	public int doRun() {
		setShoot();
		// 打僵尸
		attackZombie();
		isGameOver();
		if (sunIndex++ % 100 == 0) {
			Sun s = new Sun((int) (Math.random() * 500) + 200, -50);
			s.start();
			sun.add(s);
		}
		if (produceZombieSpeed++ % 70 == 0) {
			
		}
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		if(GamePanel.isPass || GamePanel.isGameOver){
			return 0;
		}
		return 1;
	}
	
	
}
